package com.studynotes.dev.tech.common.utils;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.util.ArrayUtil;
import com.google.common.collect.*;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.*;
import java.util.stream.Collectors;

/**
 * @author Liu XiaoJun
 * @description: TODO
 * @date 2025-11-07 12:56:57
 */
public class CollectionUtil {


    private CollectionUtil() {
        throw new IllegalStateException("Utility class");
    }

    /**
     * 包含任意值
     *
     * @param source  元数据
     * @param targets 目标
     * @return Boolean
     */
    public static boolean containsAny(Object source, Object... targets) {
        return Arrays.asList(targets).contains(source);
    }

    /**
     * 是否含有空项
     *
     * @param collections 集合
     * @return Boolean
     */
    public static boolean isAnyEmpty(Collection<?>... collections) {
        return Arrays.stream(collections).anyMatch(cn.hutool.core.collection.CollectionUtil::isEmpty);
    }

    /**
     * 过滤为列表
     *
     * @param data      元数据
     * @param predicate 过滤器
     * @param <T>       泛型
     * @return List
     */
    public static <T> List<T> filterList(Collection<T> data, Predicate<T> predicate) {
        if (CollUtil.isEmpty(data)) {
            return new ArrayList<>();
        }
        return data.stream().filter(predicate).collect(Collectors.toList());
    }

    /**
     * 通过key过滤Map
     *
     * @param data      元数据
     * @param predicate 过滤器
     * @param <K>       键泛型
     * @param <V>       值泛型
     * @return Map
     */
    public static <K, V> Map<K, V> filterMapByKey(Map<K, V> data, Predicate<K> predicate) {
        if (CollUtil.isEmpty(data)) {
            return new HashMap<>();
        }
        return data.keySet().stream().filter(predicate).collect(Collectors.toMap(Function.identity(),
                data::get));
    }

    /**
     * 通过值过滤Map
     *
     * @param data      元数据
     * @param predicate 过滤器
     * @param <K>       键泛型
     * @param <V>       值泛型
     * @return Map
     */
    public static <K, V> Map<K, V> filterMapByValue(Map<K, V> data, Predicate<V> predicate) {
        if (CollUtil.isEmpty(data)) {
            return new HashMap<>();
        }
        return data.keySet().stream().filter(key -> {
            V value = data.get(key);
            return predicate.test(value);
        }).collect(Collectors.toMap(Function.identity(), data::get));
    }

    /**
     * 过滤Map
     *
     * @param data      元数据
     * @param predicate 过滤器
     * @param <K>       键泛型
     * @param <V>       值泛型
     * @return Map
     */
    public static <K, V> Map<K, V> filterMap(Map<K, V> data, Predicate<Map.Entry<K, V>> predicate) {
        if (CollUtil.isEmpty(data)) {
            return new HashMap<>();
        }
        return data.entrySet().stream().filter(predicate).collect(Collectors.toMap(Map.Entry::getKey,
                Map.Entry::getValue));
    }

    /**
     * 过滤Map获得特定的值
     *
     * @param data      元数据
     * @param predicate 过滤器
     * @param <K>       键泛型
     * @param <V>       值泛型
     * @return V
     */
    public static <K, V> V filterMapValue(Map<K, V> data, Predicate<Map.Entry<K, V>> predicate) {
        if (CollUtil.isEmpty(data)) {
            return null;
        }
        return data.entrySet().stream().filter(predicate).reduce(null, (i, item) -> item.getValue(), (x, y) -> x);
    }

    /**
     * 去重
     *
     * @param data      元数据
     * @param keyMapper 去重规则
     * @param <T>       泛型
     * @param <R>       泛型
     * @return List
     */
    public static <T, R> List<T> distinct(Collection<T> data, Function<T, R> keyMapper) {
        if (CollUtil.isEmpty(data)) {
            return new ArrayList<>();
        }
        return distinct(data, keyMapper, (t1, t2) -> t1);
    }

    /**
     * 去重
     *
     * @param data      元数据
     * @param keyMapper 去重规则
     * @param cover     覆盖规则
     * @param <T>       泛型
     * @param <R>       泛型
     * @return List
     */
    public static <T, R> List<T> distinct(Collection<T> data, Function<T, R> keyMapper, BinaryOperator<T> cover) {
        if (CollUtil.isEmpty(data)) {
            return new ArrayList<>();
        }
        return new ArrayList<>(toMap(data, keyMapper, Function.identity(), cover).values());
    }

    /**
     * 计算为List
     *
     * @param data   元数据
     * @param mapper 计算器
     * @param <U>    泛型
     * @param <T>    泛型
     * @return List
     */
    public static <U, T> List<U> toList(Collection<T> data, Function<T, U> mapper) {
        if (CollUtil.isEmpty(data)) {
            return new ArrayList<>();
        }
        return data.stream().map(mapper).filter(Objects::nonNull).collect(Collectors.toList());
    }

    /**
     * 计算为List
     *
     * @param data      元数据
     * @param mapper    计算器
     * @param predicate 过滤器
     * @param <U>       泛型
     * @param <T>       泛型
     * @return List
     */
    public static <U, T> List<U> toList(Collection<T> data, Function<T, U> mapper, Predicate<T> predicate) {
        if (CollUtil.isEmpty(data)) {
            return new ArrayList<>();
        }
        return data.stream().filter(predicate).map(mapper).filter(Objects::nonNull).collect(Collectors.toList());
    }

    /**
     * 计算为Set
     *
     * @param data   元数据
     * @param mapper 计算器
     * @param <U>    泛型
     * @param <T>    泛型
     * @return Set
     */
    public static <U, T> Set<U> toSet(Collection<T> data, Function<T, U> mapper) {
        if (CollUtil.isEmpty(data)) {
            return new HashSet<>();
        }
        return data.stream().map(mapper).filter(Objects::nonNull).collect(Collectors.toSet());
    }

    /**
     * 计算为Set
     *
     * @param data      元数据
     * @param mapper    计算器
     * @param predicate 过滤器
     * @param <U>       泛型
     * @param <T>       泛型
     * @return Set
     */
    public static <U, T> Set<U> toSet(Collection<T> data, Function<T, U> mapper, Predicate<T> predicate) {
        if (CollUtil.isEmpty(data)) {
            return new HashSet<>();
        }
        return data.stream().filter(predicate).map(mapper).filter(Objects::nonNull).collect(Collectors.toSet());
    }

    /**
     * 计算为Map
     *
     * @param data      元数据
     * @param keyMapper key计算器
     * @param <K>       泛型
     * @param <T>       泛型
     * @return Map
     */
    public static <K, T> Map<K, T> toMap(Collection<T> data, Function<T, K> keyMapper) {
        return toMap(data, keyMapper, Function.identity());
    }

    /**
     * 计算为Map
     *
     * @param data      元数据
     * @param keyMapper key计算器
     * @param supplier  Map 构造器，在需要返回特定的 Map 时使用。第四个参数 mapSupplier 用于返回一个任意类型的 Map 实例，比如我们希望返回的 Map 是根据 Key 排序的。TreeMap::new
     * @param <K>       泛型
     * @param <T>       泛型
     * @return Map
     */
    public static <K, T> Map<K, T> toMap(Collection<T> data, Function<T, K> keyMapper,
                                         Supplier<? extends Map<K, T>> supplier) {
        return toMap(data, keyMapper, Function.identity(), supplier);
    }

    /**
     * 计算为Map
     *
     * @param data          元数据
     * @param keyMapper     key计算器
     * @param mergeFunction 冲突处理方式
     * @param <K>           泛型
     * @param <T>           泛型
     * @return Map
     */
    public static <K, T> Map<K, T> toMap(Collection<T> data, Function<T, K> keyMapper,
                                         BinaryOperator<T> mergeFunction) {
        return toMap(data, keyMapper, Function.identity(), mergeFunction);
    }

    /**
     * 计算为Map
     *
     * @param data        元数据
     * @param keyMapper   key计算器
     * @param valueMapper 值计算器
     * @param <K>         泛型
     * @param <V>         泛型
     * @param <T>         泛型
     * @return Map
     */
    public static <K, V, T> Map<K, V> toMap(Collection<T> data, Function<T, K> keyMapper, Function<T, V> valueMapper) {
        return toMap(data, keyMapper, valueMapper, (v1, v2) -> v1);
    }

    /**
     * 计算为Map
     *
     * @param data        元数据
     * @param keyMapper   key计算器
     * @param valueMapper 值计算器
     * @param supplier    特殊Map构造器
     * @param <K>         泛型
     * @param <V>         泛型
     * @param <T>         泛型
     * @return Map
     */
    public static <K, V, T> Map<K, V> toMap(Collection<T> data, Function<T, K> keyMapper, Function<T, V> valueMapper,
                                            Supplier<? extends Map<K, V>> supplier) {
        return toMap(data, keyMapper, valueMapper, (v1, v2) -> v1, supplier);
    }

    /**
     * 计算为Map
     *
     * @param data          元数据
     * @param keyMapper     key计算器
     * @param valueMapper   值计算器
     * @param mergeFunction 冲突处理方法
     * @param <K>           泛型
     * @param <V>           泛型
     * @param <T>           泛型
     * @return Map
     */
    public static <K, V, T> Map<K, V> toMap(Collection<T> data, Function<T, K> keyMapper, Function<T, V> valueMapper,
                                            BinaryOperator<V> mergeFunction) {
        return toMap(data, keyMapper, valueMapper, mergeFunction, HashMap::new);
    }

    /**
     * 计算为Map
     *
     * @param data          元数据
     * @param keyMapper     key计算器
     * @param valueMapper   值计算器
     * @param mergeFunction 冲突处理方法
     * @param supplier      特殊Map构造器
     * @param <K>           泛型
     * @param <V>           泛型
     * @param <T>           泛型
     * @return Map
     */
    public static <K, V, T> Map<K, V> toMap(Collection<T> data, Function<T, K> keyMapper, Function<T, V> valueMapper,
                                            BinaryOperator<V> mergeFunction, Supplier<? extends Map<K, V>> supplier) {
        if (CollUtil.isEmpty(data)) {
            return new HashMap<>();
        }
        return data.stream().collect(Collectors.toMap(keyMapper, valueMapper, mergeFunction, supplier));
    }

    /**
     * 按key聚合为Map
     *
     * @param data      元数据
     * @param keyMapper key计算器
     * @param <T>       泛型
     * @param <K>       泛型
     * @return Map
     */
    public static <T, K> Map<K, List<T>> toMultiMap(Collection<T> data, Function<T, K> keyMapper) {
        if (CollUtil.isEmpty(data)) {
            return new HashMap<>();
        }
        return data.stream().collect(Collectors.groupingBy(keyMapper, Collectors.mapping(t -> t, Collectors.toList())));
    }

    /**
     * 按key聚合为Map
     *
     * @param data        元数据
     * @param keyMapper   key计算器
     * @param valueMapper 值计算器
     * @param <T>         泛型
     * @param <K>         泛型
     * @param <V>         泛型
     * @return Map
     */
    public static <T, K, V> Map<K, List<V>> toMultiMap(Collection<T> data, Function<T, K> keyMapper, Function<T, V> valueMapper) {
        if (CollUtil.isEmpty(data)) {
            return new HashMap<>();
        }
        return data.stream()
                .collect(Collectors.groupingBy(keyMapper, Collectors.mapping(valueMapper, Collectors.toList())));
    }

    /**
     * 按key聚合为Map
     *
     * @param data        元数据
     * @param keyMapper   key计算器
     * @param valueMapper 值计算器
     * @param <T>         泛型
     * @param <K>         泛型
     * @param <V>         泛型
     * @return Map
     */
    public static <T, K, V> Map<K, Set<V>> toMultiMapSet(Collection<T> data, Function<T, K> keyMapper, Function<T, V> valueMapper) {
        if (CollUtil.isEmpty(data)) {
            return new HashMap<>();
        }
        return data.stream().collect(Collectors.groupingBy(keyMapper, Collectors.mapping(valueMapper, Collectors.toSet())));
    }

    /**
     * 构建常量映射Map
     *
     * @param data      元数据
     * @param keyMapper key计算器
     * @param <T>       泛型
     * @param <K>       泛型
     * @return Map
     */
    public static <T, K> Map<K, T> convertImmutableMap(Collection<T> data, Function<T, K> keyMapper) {
        if (CollUtil.isEmpty(data)) {
            return Collections.emptyMap();
        }
        ImmutableMap.Builder<K, T> builder = ImmutableMap.builder();
        data.forEach(item -> builder.put(keyMapper.apply(item), item));
        return builder.build();
    }

    /**
     * 是否包含有
     *
     * @param source     源数据
     * @param candidates 条件数据
     * @return Boolean
     */
    public static boolean containsAny(Collection<?> source, Collection<?> candidates) {
        return org.springframework.util.CollectionUtils.containsAny(source, candidates);
    }

    /**
     * 获取第一个元素
     *
     * @param data 元数据
     * @param <T>  泛型
     * @return 值
     */
    public static <T> T getFirst(Iterable<T> data) {
        return IterUtil.getFirst(data);
    }

    /**
     * 获取最后一个元素
     *
     * @param data 元数据
     * @param <T>  泛型
     * @return 值
     */
    public static <T> T getLast(Collection<T> data) {
        return CollUtil.getLast(data);
    }

    /**
     * 获取最大值
     *
     * @param from      元数据
     * @param valueFunc 计算器
     * @param <T>       泛型
     * @param <V>       泛型
     * @return 最大值
     */
    public static <T, V extends Comparable<? super V>> V getMaxValue(Collection<T> from, Function<T, V> valueFunc) {
        if (CollUtil.isEmpty(from)) {
            return null;
        }
        T t = from.stream().max(Comparator.comparing(valueFunc)).orElse(null);
        return valueFunc.apply(t);
    }

    /**
     * 获取符合条件最大的元素
     *
     * @param from       元数据
     * @param comparator 比较器
     * @param predicate  过滤器
     * @param <T>        泛型
     * @return 最大值
     */
    public static <T> T max(Collection<T> from, Comparator<T> comparator, Predicate<T> predicate) {
        if (CollUtil.isEmpty(from)) {
            return null;
        }
        return from.stream().filter(predicate).max(comparator).orElse(null);
    }

    /**
     * 获取最小值
     *
     * @param from      元数据
     * @param valueFunc 值计算器
     * @param <T>       泛型
     * @param <V>       泛型
     * @return 最小值
     */
    public static <T, V extends Comparable<? super V>> V getMinValue(Collection<T> from, Function<T, V> valueFunc) {
        if (CollUtil.isEmpty(from)) {
            return null;
        }
        T t = from.stream().min(Comparator.comparing(valueFunc)).orElse(null);
        return valueFunc.apply(t);
    }

    /**
     * 获取符合条件的最小元素
     *
     * @param from       元数据
     * @param comparator 比较器
     * @param predicate  过滤器
     * @param <T>        泛型
     * @return 最小值
     */
    public static <T> T min(Collection<T> from, Comparator<T> comparator, Predicate<T> predicate) {
        if (CollUtil.isEmpty(from)) {
            return null;
        }
        return from.stream().filter(predicate).min(comparator).orElse(null);
    }

    /**
     * 获取集合的和
     *
     * @param from        元数据
     * @param valueFunc   值计算方式
     * @param accumulator 和计算方式
     * @param <T>         泛型
     * @param <V>         泛型
     * @return 和
     */
    public static <T, V extends Comparable<? super V>> V getSumValue(Collection<T> from, Function<T, V> valueFunc, BinaryOperator<V> accumulator) {
        if (CollUtil.isEmpty(from)) {
            return null;
        }
        return from.stream().map(valueFunc).reduce(accumulator).orElse(null);
    }

    /**
     * 判空添加元素
     *
     * @param coll 集合
     * @param item 元素
     * @param <T>  泛型
     */
    public static <T> void addIfNotNull(Collection<T> coll, T item) {
        Optional.ofNullable(item).ifPresent(coll::add);
    }

    /**
     * 获取符合条件的第一个元素
     *
     * @param data      元数据
     * @param predicate 过滤器
     * @param <T>       泛型
     * @return 值
     */
    public static <T> T findFirst(List<T> data, Predicate<T> predicate) {
        if (CollUtil.isEmpty(data)) {
            return null;
        }
        return data.stream().filter(predicate).findFirst().orElse(null);
    }

    /**
     * 构建
     *
     * @param item 元素
     * @param <T>  泛型
     * @return 集合
     */
    public static <T> Collection<T> singleton(T item) {
        return item == null ? Collections.emptyList() : Collections.singleton(item);
    }

    /**
     * 归一集合
     *
     * @param data        元数据
     * @param identity    初始值
     * @param accumulator 累加器
     * @param <T>         泛型
     * @return 值
     */
    public static <T> T reduceCollection(Collection<T> data, T identity, BinaryOperator<T> accumulator) {
        if (CollUtil.isEmpty(data)) {
            return identity;
        }
        return data.stream().reduce(identity, accumulator);
    }

    /**
     * 归一集合
     *
     * @param data        元数据
     * @param identity    初始值
     * @param accumulator 累加器
     * @param <T>         泛型
     * @param <U>         泛型
     * @return 值
     */
    public static <T, U> U reduceCollection(Collection<T> data, U identity, BiFunction<U, ? super T, U> accumulator) {
        if (CollUtil.isEmpty(data)) {
            return identity;
        }
        return data.stream().reduce(identity, accumulator, (x, y) -> null);
    }

    /**
     * 归一集合
     *
     * @param data        元数据
     * @param identity    初始值
     * @param accumulator 累加器
     * @param combiner    并行合并器
     * @param <T>         泛型
     * @param <U>         泛型
     * @return 值
     */
    public static <T, U> U reduceCollection(Collection<T> data, U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner) {
        if (CollUtil.isEmpty(data)) {
            return identity;
        }
        return data.stream().reduce(identity, accumulator, combiner);
    }

    /**
     * 归一集合
     *
     * @param data        元数据
     * @param accumulator 累加器
     * @param <T>         泛型
     * @return 值
     */
    public static <T> T reduceCollection(Collection<T> data, BinaryOperator<T> accumulator) {
        if (CollUtil.isEmpty(data)) {
            return null;
        }
        return data.stream().reduce(accumulator).orElse(null);
    }

    /**
     * BigDecimal求和
     *
     * @param data 元数据
     * @return 和
     */
    public static BigDecimal bigDecimalSum(Collection<BigDecimal> data) {
        return reduceCollection(data, BigDecimal.ZERO, BigDecimal::add);
    }

    /**
     * Integer求和
     *
     * @param data 元数据
     * @return 和
     */
    public static Integer integerSum(Collection<Integer> data) {
        return reduceCollection(data, Integer::sum);
    }

    /**
     * Double求和
     *
     * @param data 元数据
     * @return 和
     */
    public static Double doubleSum(Collection<Double> data) {
        return reduceCollection(data, Double::sum);
    }

    /**
     * 归一MAP
     *
     * @param data        元数据
     * @param identity    初始值
     * @param accumulator 累加器
     * @param <K>         泛型
     * @param <V>         泛型
     * @param <R>         泛型
     * @return 值
     */
    public static <K, V, R> R reduceMap(Map<K, V> data, R identity, BiFunction<R, V, R> accumulator) {
        if (CollUtil.isEmpty(data)) {
            return identity;
        }
        return data.values().stream().reduce(identity, accumulator, (x, y) -> null);
    }

    /**
     * 归一MAP
     *
     * @param data        元数据
     * @param identity    初始值
     * @param accumulator 累加器
     * @param combiner    并行合并器
     * @param <K>         泛型
     * @param <V>         泛型
     * @param <R>         泛型
     * @return 值
     */
    public static <K, V, R> R reduceMap(Map<K, V> data, R identity, BiFunction<R, V, R> accumulator, BinaryOperator<R> combiner) {
        if (CollUtil.isEmpty(data)) {
            return identity;
        }
        return data.values().stream().reduce(identity, accumulator, combiner);
    }

    /**
     * set
     *
     * @param objs 元数据
     * @param <T>  泛型
     * @return Set
     */
    @SafeVarargs
    public static <T> Set<T> asSet(T... objs) {
        return new HashSet<>(Arrays.asList(objs));
    }

    /**
     * 转换数组
     *
     * @param from   元数据
     * @param mapper 转换器
     * @param <T>    泛型
     * @param <V>    泛型
     * @return 数组
     */
    public static <T, V> V[] toArray(Collection<T> from, Function<T, V> mapper) {
        return toArray(toList(from, mapper));
    }

    /**
     * 转换数组
     *
     * @param from 元数据
     * @param <T>  泛型
     * @return 数组
     */
    @SuppressWarnings("unchecked")
    public static <T> T[] toArray(Collection<T> from) {
        if (CollUtil.isEmpty(from)) {
            return (T[]) (new Object[0]);
        }
        return ArrayUtil.toArray(from, (Class<T>) IterUtil.getElementType(from.iterator()));
    }

    /**
     * 转化为表格
     *
     * @param data         元数据
     * @param rowMapper    行计算器
     * @param columnMapper 列计算器
     * @param valueMapper  值计算器
     * @param <R>          泛型
     * @param <C>          泛型
     * @param <V>          泛型
     * @param <T>          泛型
     * @return 表格
     */
    public static <R, C, V, T> Table<R, C, V> toTable(Collection<T> data, Function<T, R> rowMapper, Function<T, C> columnMapper, Function<T, V> valueMapper) {
        Table<R, C, V> table = HashBasedTable.create();
        if (CollUtil.isEmpty(data)) {
            return table;
        }
        data.forEach(item -> table.put(rowMapper.apply(item), columnMapper.apply(item), valueMapper.apply(item)));
        return table;
    }

    /**
     * 转化为Multimap
     *
     * @param data 元数据
     * @param keyMapper key计算器
     * @param <K> key泛型
     * @param <T> 元数据泛型
     * @return multimap
     */
    public static <K, T> Multimap<K, T> toMultimap(Collection<T> data, Function<T, K> keyMapper) {
        return toMultimap(data, keyMapper, Function.identity());
    }

    /**
     * 转化为Multimap
     *
     * @param data 元数据
     * @param keyMapper key计算器
     * @param valueMapper value计算器
     * @param <K> key泛型
     * @param <V> value泛型
     * @param <T> 元数据泛型
     * @return multimap
     */
    public static <K, V, T> Multimap<K, V> toMultimap(Collection<T> data, Function<T, K> keyMapper, Function<T, V> valueMapper) {
        Multimap<K, V> map = HashMultimap.create();
        return data.stream().reduce(map, (init, item) -> {
            init.put(keyMapper.apply(item), valueMapper.apply(item));
            return init;
        }, (x, y) -> {
            x.putAll(y);
            return x;
        });
    }

    /**
     * 转化为Multiset
     *
     * @param data 元数据
     * @param <T> 元数据泛型
     * @return multiset
     */
    public static <T> Multiset<T> toMultiset(Collection<T> data) {
        Multiset<T> set = HashMultiset.create();
        if (CollUtil.isEmpty(data)) {
            return set;
        }
        set.addAll(data);
        return set;
    }

    /**
     * 转化为Multiset
     *
     * @param data 元数据
     * @param valueMapper 值计算器
     * @param <V> value泛型
     * @param <T> 元数据泛型
     * @return multiset
     */
    public static <V, T> Multiset<V> toMultiset(Collection<T> data, Function<T, V> valueMapper) {
        Multiset<V> set = HashMultiset.create();
        if (CollUtil.isEmpty(data)) {
            return set;
        }
        return data.stream().reduce(set, (init, item) -> {
            init.add(valueMapper.apply(item));
            return init;
        }, (x, y) -> {
            x.addAll(y);
            return x;
        });
    }

    /**
     * 转化为BiMap
     *
     * @param data 元数据
     * @param keyMapper key计算器
     * @param valueMapper value计算器
     * @param <K> key泛型
     * @param <V> value泛型
     * @param <T> 元数据泛型
     * @return BiMap
     */
    public static <K, V, T> BiMap<K, V> toBiMap(Collection<T> data, Function<T, K> keyMapper, Function<T, V> valueMapper) {
        BiMap<K, V> map = HashBiMap.create();
        if (CollUtil.isEmpty(data)) {
            return map;
        }
        return data.stream().reduce(map, (init, item) -> {
            init.put(keyMapper.apply(item), valueMapper.apply(item));
            return init;
        }, (x, y) -> null);
    }

    /**
     * 是否包含任意一个
     *
     * @param obj  目标对象
     * @param objs 目标对象数组
     * @param <T>  泛型
     * @return 是否包含任意一个
     */
    public static <T> boolean equalsAny(T obj, T... objs) {
        return Arrays.asList(objs).contains(obj);
    }

}
